<?php
/**
 * DatabaseSession
 * 
 * Session存数据库
 * 存数据库前，需要建session表，表名默认为session，可以自定义
 * 自定义表名时，需要将表名做为参数赋给构造方法
 * 如果修改表的字段，需要修改本类代码
 * CREATE TABLE session (
 *     session_id      char(32)     NOT NULL COMMENT 'SESSION_ID',
 * 	   dt_start        datetime     NOT NULL COMMENT 'session_start的时间',
 * 	   dt_last_access  datetime     NOT NULL COMMENT '最后一次访问SESSION的时间',
 *     data            text         NOT NULL COMMENT 'SESSION的内容',
 *     url_last_access varchar(255) NOT NULL COMMENT '最后一次访问SESSION的页面',
 *     ip_last_access  char(16)     NOT NULL COMMENT '最后一次访问SESSION的IP地址'
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 * 
 * @author   songhuan <iphper@yeah.net>
 * @version   $Id: DatabaseSession.php 1 2011-03-02 14:12:00Z $
 */
class DatabaseSession
{
	protected $_db = null;
	protected $_table = '';
	
	public function __construct($table = 'session')
	{
		$this->_table = $table;
	}
	
	public function open($path, $name)
	{
		try 
		{
			$this->_db = Database::getInstance();
		}
		catch (Exception $e)
		{
			return false;
		}
		return true;
	}
	
	public function close()
	{
		$this->_db = null;
		return true;
	}
	
	public function read($session_id)
	{
		$row = $this->_db->find($this->_table, array('session_id = ?', $session_id), 'data', PDO::FETCH_ASSOC);
		return $row ? $row['data'] : '';
	}
	
	public function write($session_id, $data)
	{
		$param = array('dt_last_access'  => date('Y-m-d H:i:s'), 'url_last_access' => Helper::getUrl(), 
						'ip_last_access'  => Helper::getIp(), 'data' => $data);
		$row = $this->_db->find($this->_table, array('session_id = ?', $session_id), 'COUNT(*)', PDO::FETCH_ASSOC);
		if ($row['COUNT(*)'] > 0) 
			$result = $this->_db->update($this->_table, $param, array('session_id = ?', $session_id));
		else 
		{
			$param['session_id'] = $session_id;
			$param['dt_start'] = $param['dt_last_access'];
			$result = $this->_db->insert($this->_table, $param);
		}
		
		return $result > 0;
	}
	
	public function destroy($session_id)
	{
		$rowCount = $this->_db->delete($this->_table, array('session_id = ?', $session_id));
		return $rowCount > 0;
	}
	
	public function gc($ttl)
	{
		$end = date('Y-m-d H:i:s', mktime() - $ttl);
		$rowCount = $this->_db->delete($this->_table, array('dt_last_access < ?', $end));
		return $rowCount > 0;
	}
	
	public function __destruct()
	{
		session_write_close();
	}
}

$session = new DatabaseSession(V::$config['session']['table']);
session_set_save_handler(
	array($session, 'open'),
	array($session, 'close'),
	array($session, 'read'),
	array($session, 'write'),
	array($session, 'destroy'),
	array($session, 'gc')
);
